﻿using ER.Dynamic;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace ER.Tests.DynamicWebApp.Data.Dynamic
{
    public class RuntimeDbContextBuilder
    {
        public static readonly string NameSpace="ER.Tests.DynamicWebApp.Data";
        const string ConnectionStringKey = "ConnectionName";
        const string CheckCodeFirstAutoMigrateKey = "IsAutoMigration";
        public static readonly TypeEmiter TypeDbContextEmiter;
        static RuntimeDbContextBuilder()
        {
            TypeEmiter typeEmployeeEmiter = Emiter.CreateTypeEmiter(NameSpace + ".Employee");
            typeEmployeeEmiter.AddPropertyEmiter("EmployeeId", typeof(int));
            typeEmployeeEmiter.AddPropertyEmiter("Name", typeof(String));
            PropertyEmiter ageProp = typeEmployeeEmiter.AddPropertyEmiter("Age", typeof(int));
            typeEmployeeEmiter.Emit();

            TypeEmiter typeClassEmiter = Emiter.CreateTypeEmiter(NameSpace + ".Class");
            typeClassEmiter.AddPropertyEmiter("ClassId", typeof(int));
            typeClassEmiter.AddPropertyEmiter("ClassName", typeof(String));
            typeClassEmiter.Emit();

            TypeEmiter typeStudentEmiter = Emiter.CreateTypeEmiter(NameSpace + ".Student");
            typeStudentEmiter.AddPropertyEmiter("StudentId", typeof(int));
            typeStudentEmiter.AddPropertyEmiter("Name", typeof(String));
            typeStudentEmiter.AddPropertyEmiter("Class", typeClassEmiter);
            typeStudentEmiter.AddPropertyEmiter("ClassId", typeof(int));
            typeStudentEmiter.Emit();

            TypeDbContextEmiter = Emiter.CreateTypeEmiter(NameSpace + ".RuntimeDbContext");
            TypeDbContextEmiter.BaseType = typeof(DbContext);
            TypeDbContextEmiter.AddConstructorEmiter(new []{typeof(string)});
            var stDbSet = typeof(DbSet<>).MakeGenericType(typeStudentEmiter);
            var emDbSet = typeof(DbSet<>).MakeGenericType(typeEmployeeEmiter);
            RuntimeDbContextBuilder.TypeDbContextEmiter.AddPropertyEmiter("Students", stDbSet);
            RuntimeDbContextBuilder.TypeDbContextEmiter.AddPropertyEmiter("Employees", emDbSet);
            TypeDbContextEmiter.Emit();
            if (ConfigurationManager.AppSettings[CheckCodeFirstAutoMigrateKey] != "true")
            {
                typeof(Database).GetMethod("SetInitializer").MakeGenericMethod(TypeDbContextEmiter.Type).Invoke(null, new Object[] { null });
            }
        }
        public static DbContext CreateDbContext()
        {
            string connectString = ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings[ConnectionStringKey]].ConnectionString;
            return RuntimeDbContextBuilder.TypeDbContextEmiter.CreateObject(connectString) as DbContext;
        }
    }
}